<?php
declare (strict_types = 1);

namespace app\home\controller;

use app\BaseController;
use app\common\model\Config;
use app\common\model\Post\Cate;
use app\common\model\Post\Post as PostModel;
use app\common\model\Post\Comment as CommentModel;
use app\common\model\User\Record;
use app\common\model\User\User;
use app\common\validate\Post\Post as PostValidate;
use app\common\validate\User\Record as RecordValidate;
use app\home\middleware\Auth;
use think\exception\ValidateException;
use think\facade\View;

class Post extends BaseController
{
    // 控制器中间件
    protected $middleware = [
        Auth::class
    ];

    // 控制器初始化
    protected function initialize()
    {
        parent::initialize();

        // 实例化模型
        $this->CateModel = new Cate();

        $this->PostModel = new PostModel();
        $this->CommentModel = new CommentModel();

        $this->UserModel = new User();

        $this->RecordModel = new Record();

        $this->ConfigModel = new Config();
    }

    // 添加帖子
    public function add()
    {
        if($this->request->isPost())
        {
            // 接收验证码
            $vercode = $this->request->param('vercode','','trim');

            // 验证验证码是否正确
            if(!captcha_check($vercode))
            {
                $this->error('验证码错误，请重新输入');
            }

            //  发帖逻辑 
            //  1判断积分是否充足
            //  2、发帖(insert) pre_post
            //  3、扣积分 => 用户表(update)
            //  4、消费记录 => 记录用户因为什么花的积分(insert)
            //  innodb 事务、行级锁定机制、外键约束条件 崩溃恢复

            //  事务 是保证一个流程中所执行的sql语句能够完整执行

            // 开启事务
            $this->PostModel->startTrans();
            $this->UserModel->startTrans();
            $this->RecordModel->startTrans();

            // 判断积分是否充足
            // 帖子状态
            $state = $this->request->param('state',0);

            // 悬赏积分
            $point = $this->request->param('point',0);
            
            // 需要在config表里新增发帖的状态获取相应的积分
            // 置顶 => 1
            // 精华 => 2
            // 热门 => 3

            // 根据发布帖子的状态获取相应的发布需要扣除的积分
            $StatePoint = $this->ConfigModel->where(['key' => "PostState{$state}"])->value('value');

            // 如果当帖子状态为0 => 查询结果为空 => 这里需要处理,当为null时需要变成0
            $StatePoint = $StatePoint ? $StatePoint : (String)0;//

            // 悬赏积分 + 帖子状态积分
            $PostPoint = bcadd($point,$StatePoint);

            // 判断用户的积分是否充足
            $UpdatePoint = bcsub((String)$this->request->LoginUser['point'],$PostPoint);

            // 判断用户积分是否小于0
            if($UpdatePoint < 0)
            {
                $this->error('积分不足，请及时充值');
                
            }

            // 接收提交过来的数据
            $params = $this->request->param();

            // 组装发帖的数据
            $PostData = [
                'title' => $params['title'],
                'content' => $params['content'],
                'point' => $PostPoint,
                'state' => $state,
                'userid' => $this->request->LoginUser['id'],
                'cateid' => $params['cateid'],
            ];
            
            // 验证数据
            try {
                // 调用验证器
                validate(PostValidate::class)->check($PostData);
            } catch (ValidateException $e) {
                // 捕获异常
                $this->error($e->getError());
            }
            // 插入数据库
            $PostStatus = $this->PostModel->save($PostData);

            // 封装用户数据 => 如果发帖子成功就需要扣除相应积分
            $UserData = [
                'point' => $UpdatePoint
            ];


            // 更新数据库
            $User = User::find($this->request->LoginUser['id']);

            // 更新数据
            $UserStatus = $User->save($UserData);

            if(true !== $UserStatus)
            {
                // 如果积分更新失败后，帖子表要回滚
                $this->PostModel->rollback();
                $this->error($User->getError());
                
            }

            // 更新消费记录
            $RecordData = [
                'point' => $PostPoint,
                'content'=> "您发布了：【{$params['title']}】的悬赏帖子，消耗了【{$PostPoint}】个积分",
                'state' => 1,
                'userid' => $this->request->LoginUser['id']
            ];

            try {
                validate(RecordValidate::class)->check($RecordData);
            } catch (ValidateException $e) {
                $this->PostModel->rollback();
                $this->UserModel->rollback();
                $this->error($e->getError());
            }
            
            $RecordStatus = $this->RecordModel->save($RecordData);

            if(true !== $PostStatus || true !== $UserStatus || true !== $RecordStatus)
            {
                $this->PostModel->rollback();
                $this->UserModel->rollback();
                $this->RecordModel->rollback();
                $this->error('发布帖子失败');
            }else{
                $this->PostModel->commit();
                $this->UserModel->commit();
                $this->RecordModel->commit();
                $this->success('发布帖子成功','/home/index/index');
            }
            

        }

        // 帖子的状态 置顶 精华 热门
        $StateList = $this->PostModel->state();

        // 查询分类的数据
        $CateList = $this->CateModel->order('weigh','desc')->limit(7)->select();

        return View::fetch('',[
            'CateList' => $CateList,
            'StateList' => $StateList
        ]);
    }

    // 编辑帖子
    public function edit()
    {
        // 接收帖子id
        $postid = $this->request->param('postid',0,'trim');

        // 查询数据
        $post = PostModel::withJoin(['user'],'LEFT')->find($postid);

        // 判断是否帖子
        if(!$post)
        {
            $this->error('帖子不存在');
        }


        if($this->request->isPost())
        {
            // 接收验证码
            $vercode = $this->request->param('vercode','','trim');

            // 验证验证码是否正确
            if(!captcha_check($vercode))
            {
                $this->error('验证码错误，请重新输入');
            }

            // 接收参数
            $title = $this->request->param('title', '', 'trim');
            $content = $this->request->param('content', '', 'trim');
            $cateid = $this->request->param('cateid', '', 'trim');

            //组装数据
            $PostData = [
                'id' => $post['id'],
                'title' => $title,
                'content' => $content,
                'cateid' => $cateid,
            ];

            try {
                validate(PostValidate::class)->scene('edit')->check($PostData);
            } catch (ValidateException $e) {
                $this->error($e->getError());
            }

            // 更新数据
            $Post = PostModel::find($post['id']);
            $result = $Post->save($PostData);

            if($result !== true)
            {
                $this->error('编辑帖子失败');
            }else{
                $this->success('编辑帖子成功',(String)url('home/index/info',['postid' => $post['id']]));
            }
        }

        // 帖子的状态 置顶 精华 热门
        $StateList = $this->PostModel->state();

        // 查询分类的数据
        $CateList = $this->CateModel->order('weigh','desc')->limit(7)->select();
        return View::fetch('',[
            'CateList' => $CateList,
            'StateList' => $StateList,
            'post' => $post,
        ]);
    }

    // 删除
    public function del()
    {
        if($this->request->isAjax())
        {
            $id = $this->request->param('id',0);

            $post = PostModel::find($id);

            if(!$post)
            {
                $this->error('帖子不存在');
            }

            

            $this->CommentModel->startTrans();
            $this->PostModel->startTrans();

            $PostStatus = $post->delete();
            $Comment = CommentModel::where(['postid' => $post['id']])->update(['deletetime' => time()]);
            

            if($PostStatus !== true || $Comment < 0)
            {
                $this->CommentModel->rollback();
                $this->PostModel->rollback();
                $this->error('删除失败');

            }else{
                $this->CommentModel->commit();
                $this->PostModel->commit();
                $this->success('删除成功');
            }
        }
    }
}
